import 'dart:convert';

import 'package:coin_genarate/coin_generate.dart';
import 'package:db_util/wx_wallet_db.dart';
import 'package:flustars/flustars.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_coin_util/coin_util_import.dart';
import 'package:flutter_coin_util/model/wallet_list_model.dart';

import 'aes_util.dart';
import '../constant/common.dart';
import 'database_util.dart';

typedef CoinListCallback = void Function(List<CoinsBean> coins); //

enum AmountSuffixType { symbol, letter, none }

class CoinManager {
  static CoinManager _manager = CoinManager._();

  CoinManager._();

  factory CoinManager() => _manager;

  static String walletName;

  static String backHomeSourcePage;

  CoinListCallback callback;

  static List<String> mnemonicList = [
    "science menu teach digital dolphin nice cable design museum gym method race",
    "pistol enable morning fan oppose aerobic check dad soda awesome prefer option",
    "violin minor nurse fresh broccoli dignity together spirit pistol either auction neck",
    "vendor shy tennis canyon section fashion chalk general crunch very panel goddess",
    "good east sell harsh cake bounce bicycle please coral enlist anchor heart",
    "nose grace cheap upon owner naive risk device spread winter refuse cost",
    "payment fatal boat photo symptom dog rocket gospel foot box sell praise"
  ];

  void setCoinListListener(CoinListCallback coinListCallback) {
    this.callback = coinListCallback;
  }

  /// 数组入参
  static List<GenCoin> getGenCoinList() {
    List<GenCoin> genCoinList = List();
    genCoinList.add(GenCoin(name: "BTC", path: "m/44'/0'/0'/0/0"));
    genCoinList.add(GenCoin(name: "ETH", path: "m/44'/60'/0'/0/0"));
    genCoinList.add(GenCoin(name: "EOS", path: "m/44'/194'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "ELF", path: "m/44'/1616'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "CMT", path: "m/44'/302'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "BHP", path: "m/44'/547'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "BTT", path: "m/44'/34952'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "CITY", path: "m/44'/1926'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "GAME", path: "m/44'/101'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "HASH", path: "m/44'/505'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "ICX", path: "m/44'/74'/0'/0/0"));
    genCoinList.add(GenCoin(name: "NAS", path: "m/44'/2718'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "TRX", path: "m/44'/195'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "THETA", path: "m/44'/500'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "XPC", path: "m/44'/398'/0'/0/0"));
//    genCoinList.add(GenCoin(name: "BTM", path: "m/44'/153'/0'/0/0"));
    return genCoinList;
  }

  ///获取SDK方的数据
  Future<List<Coin>> getOriginAllData(List<GenCoin> genCoinList) async {
    String mnemonic = AESUtil.decryptString((await DatabaseUtil.getWalletMnemonic()).toString());
    List<GenCoin> genCoinList = getGenCoinList();
    Map<String, dynamic> param = {'mnemonic': mnemonic, 'coinNames': genCoinList};

    /// compute创建异步线程生成币种
    List<Coin> coins = await compute(getCoins, param);
    return Future.value(coins);
  }

  static Future<List<Coin>> getCoins(Map<String, dynamic> data) async {
    final manager = CoinGenerateManager();
    return await manager.generateCoinList(data['mnemonic'], data['coinNames']);
  }

  /// 处理币种数据
  void handleListCoinData(List<Coin> list) async {
    print('isolate Data：$list');
    List<CoinsBean> allCoinList = List();
    list.forEach((coin) {
      CoinsBean bean = CoinsBean();
      bean.title = coin.name;
      bean.address = coin.addr;
      bean.privateKey = coin.privateKey;
      bean.publicKey = coin.publicKey;
      switch (coin.name) {
        case "BTC":
          bean.isSelected = true;
          bean.coinid = "Bitcoin";
          bean.img = "assets/images/btc_icon.png";
          bean.num = "8.00000000";
          bean.cnyBalance = "93682.16";
          bean.cnyMoney = "749457.28";
          break;
        case "ETH":
          bean.isSelected = false;
          bean.coinid = "Ether";
          bean.img = "assets/images/eth_icon.png";
          bean.num = "300.02000000";
          bean.cnyBalance = "2602.42";
          bean.cnyMoney = "780778.05";
          break;
        case "EOS":
          bean.isSelected = false;
          bean.coinid = "EOS";
          bean.img = "assets/images/eos_icon.png";
          bean.num = "2.03250000";
          bean.cnyBalance = "250.00";
          bean.cnyMoney = "508.125";
          break;
        case "ELF":
          bean.isSelected = false;
          bean.coinid = "AELF";
          bean.img = "assets/images/elf_icon.png";
          bean.num = "12.03600000";
          bean.cnyBalance = "0.52";
          bean.cnyMoney = "6.25872";
          break;
        case "CMT":
          bean.isSelected = false;
          bean.coinid = "Community";
          bean.img = "assets/images/cmt_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "BHP":
          bean.isSelected = false;
          bean.coinid = "BHP";
          bean.img = "assets/images/bhp_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "BTT":
          bean.isSelected = false;
          bean.coinid = "ByteTrade";
          bean.img = "assets/images/btt_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "CITY":
          bean.isSelected = false;
          bean.coinid = "City Coin";
          bean.img = "assets/images/city_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "GAME":
          bean.isSelected = false;
          bean.coinid = "GameCredits";
          bean.img = "assets/images/game_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "HASH":
          bean.isSelected = false;
          bean.coinid = "Provenance";
          bean.img = "assets/images/hash_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "ICX":
          bean.isSelected = false;
          bean.coinid = "ICON";
          bean.img = "assets/images/icx_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "NAS":
          bean.isSelected = false;
          bean.coinid = "Nebulas";
          bean.img = "assets/images/nas_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "0.5";
          bean.cnyMoney = "0.00";
          break;
        case "TRX":
          bean.isSelected = false;
          bean.coinid = "Tron";
          bean.img = "assets/images/trx_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "0.16";
          bean.cnyMoney = "0.00";
          break;
        case "THETA":
          bean.isSelected = false;
          bean.coinid = "Theta";
          bean.img = "assets/images/theta_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "XPC":
          bean.isSelected = false;
          bean.coinid = "XPChain";
          bean.img = "assets/images/xpc_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
        case "BTM":
          bean.isSelected = false;
          bean.coinid = "Bytom";
          bean.img = "assets/images/btm_icon.png";
          bean.num = "0.00000000";
          bean.cnyBalance = "250.0";
          bean.cnyMoney = "0.00";
          break;
      }
      allCoinList.add(bean);
    });
    print("_allCoinList=======>$allCoinList");
    List<String> walletName = await DatabaseUtil.getTableList();
    await DatabaseUtil.saveWalletCoinsData(walletName[0], allCoinList);

//    await createNewWalletData(allCoinList);
    callback(allCoinList);
  }

  Future createNewWalletData(List<CoinsBean> allCoinList) async {
    String randomMnemonic = CoinGenerateManager().generateMnemonic();
    await WXDataBaseUtil.createTable("wx_table_hello");
    await WXDataBaseUtil.insert("wx_table_hello", "mnemonic_string", AESUtil.encryptString(randomMnemonic));
    await WXDataBaseUtil.insert("wx_table_hello", "verified_mnemonic", "true");

    List<CoinsBean> newList = [];
    CoinsBean bean = CoinsBean();
    bean.title = "ETH";
    bean.address = "coin.addr";
    bean.privateKey = "coin.privateKey";
    bean.publicKey = "coin.publicKey";
    bean.isSelected = true;
    bean.coinid = "Ether";
    bean.img = "assets/images/eth_icon.png";
    bean.num = "3.02000000";
    bean.cnyBalance = "2602.42";
    bean.cnyMoney = "7859.3084";
    newList.add(bean);
    await DatabaseUtil.saveWalletCoinsData("wx_table_hello", newList);
    await DatabaseUtil.saveTransferRecord("wx_table_hello", "[]");
  }

  /// 生成全部数据和初始化列表数据
  Future<List<CoinsBean>> getListData() async {
    List<CoinsBean> _coinList = <CoinsBean>[];

    List<String> wallets = await DatabaseUtil.getWalletNameList();
    dynamic allListData = await DatabaseUtil.getWalletCoinsData(DatabaseUtil.walletNameToTableName(wallets[0]));

    if (json.decode(allListData.toString()).isEmpty) {
      _coinList.clear();
      List<Coin> list = await getOriginAllData(getGenCoinList());
      handleListCoinData(list);
    } else {
      _coinList.addAll(CoinsBean.toList(json.decode(allListData.toString())));
      callback(_coinList);
    }
    return _coinList;
  }

  List<CoinsBean> getSelectedCoinList(List<CoinsBean> allCoins) {
    List<CoinsBean> list = [];
    allCoins.forEach((coin) {
      if (coin.isSelected) {
        list.add(coin);
      }
    });
    return list;
  }

  removeSelectedCoin(String walletName, String title) async {
    WalletBean bean = await getWalletDataFromWalletName(walletName: walletName);
    for (CoinsBean tempCoin in bean.coins.coins) {
      if (tempCoin.title == title) {
        tempCoin.isSelected = false;
      }
    }
    DatabaseUtil.saveWalletCoinsData(DatabaseUtil.walletNameToTableName(walletName), bean.coins.coins);
  }

  saveSelectedCoin(String walletName, String title) async {
    WalletBean bean = await getWalletDataFromWalletName(walletName: walletName);
    for (CoinsBean tempCoin in bean.coins.coins) {
      if (tempCoin.title == title) {
        tempCoin.isSelected = true;
      }
    }
    DatabaseUtil.saveWalletCoinsData(DatabaseUtil.walletNameToTableName(walletName), bean.coins.coins);
  }

  /// 获取当前钱包所有/已选币种列表
  Future<List<CoinsBean>> getCoinList(String wallet, bool isSelect) async {
    List<CoinsBean> _coinList = <CoinsBean>[];
    dynamic coins = await DatabaseUtil.getWalletCoinsData(DatabaseUtil.walletNameToTableName(wallet));
    _coinList = CoinsBean.toList(json.decode(coins.toString()));
    if (isSelect) {
      _coinList = getSelectedCoinList(_coinList);
    }
    if (_coinList.isEmpty) return [];
    return _coinList;
  }

  updateCoinDetail(String wallet, String coinName, String upDown, String costCnyMoney, String transferType) async {
    if (coinName.isEmpty || upDown.isEmpty || costCnyMoney.isEmpty) return;

    /// 更新全部数据
    List<CoinsBean> coinList = await getCoinList(wallet, false);

    coinList.forEach((bean) {
      if (bean.title == coinName) {
        if (transferType == "0") {
          bean.num = (double.parse(bean.num) - double.parse(upDown)).toString();
          bean.cnyMoney = (double.parse(bean.cnyMoney) - double.parse(costCnyMoney)).toString();
        } else {
          bean.num = (double.parse(bean.num) + double.parse(upDown)).toString();
          bean.cnyMoney = (double.parse(bean.cnyMoney) + double.parse(costCnyMoney)).toString();
        }
      }
    });
    await DatabaseUtil.saveWalletCoinsData(DatabaseUtil.walletNameToTableName(wallet), coinList);
  }

  Future<CoinsBean> getSingleCoinDetailModel(String wallet, String coinName) async {
    if (coinName.isEmpty) return null;
    CoinsBean bean = CoinsBean();
    List<CoinsBean> coinList = await getCoinList(wallet, false);
    coinList.forEach((coin) {
      if (coin.title == coinName) {
        bean = coin;
      }
    });
    return bean;
  }

  String getTotalAssetsCNY(List<WalletBean> allWalletData) {
    num totalAssets = 0.0;
    allWalletData.forEach((walletBean) {
      List<CoinsBean> coinList = walletBean.coins.coins;
      num walletAssets = 0.0;
      coinList.forEach((coin) {
        walletAssets += NumUtil.getNumByValueStr(coin.cnyMoney, fractionDigits: 8);
      });
      totalAssets += walletAssets;
    });
    return totalAssets.toString();
  }

  String getWalletAssetsCNY(List<CoinsBean> coinList) {
    num totalAssets = 0.0;
    coinList.forEach((coin) {
      totalAssets += NumUtil.getNumByValueStr(coin.cnyMoney, fractionDigits: 8);
    });
    return totalAssets.toString();
  }

  /// 获取bean形式的所有钱包数据
  Future<List<WalletBean>> getWalletAllData(bool isSelect) async {
    List<WalletBean> allWalletData = List();

    /// 完整数据的Map
    List<Map<String, dynamic>> allWalletMapData = await DatabaseUtil.getAllWalletData();
    allWalletMapData.forEach((walletData) {
      /// 单个钱包的model
      WalletBean walletBean = WalletBean();
      walletBean.walletName = walletData["wallet_name"].toString();
      walletBean.verifiedMnemonic = walletData["verified_mnemonic"].toString();
      walletBean.mnemonicString = walletData["mnemonic_string"].toString();

      /// 单个钱包的币种信息
      WalletCoinListModel coinsBean = WalletCoinListModel.fromMap(walletData);
      if (isSelect) {
        coinsBean.coins = getSelectedCoinList(coinsBean.coins);
      }
      walletBean.coins = coinsBean;

      /// 单个钱包的转账信息
      WalletTransferRecordListModel walletTransferRecordListModel = WalletTransferRecordListModel.fromMap(walletData);
      walletBean.walletTransferRecordListModel = walletTransferRecordListModel;

      allWalletData.add(walletBean);

      WalletListModel model = WalletListModel();
      model.walletList = allWalletData;
    });
    return allWalletData;
  }

  /// 根据钱包名获取其数据
  Future<WalletBean> getWalletDataFromWalletName({@required String walletName, bool isSelect = false}) async {
    List<WalletBean> allWalletData = await getWalletAllData(isSelect);
    WalletBean walletBean = WalletBean();
    allWalletData.forEach((walletData) {
      if (walletName == walletData.walletName) {
        walletBean = walletData;
      }
    });
    return walletBean;
  }

  /// 根据钱包名获取数据
  WalletBean getWalletData(
      {@required String walletName, @required List<WalletBean> walletList, bool isSelect = false}) {
    WalletBean walletBean = WalletBean();
    walletList.forEach((walletData) {
      if (walletName == walletData.walletName) {
        walletBean = walletData;
      }
    });
    return walletBean;
  }

  /// 根据法币类型显示金额
  String getAmountFromFB(String amount, {AmountSuffixType type = AmountSuffixType.letter}) {
    String coinModel = SpUtil.getString(Constant.coinModel, defValue: "rmb");
    double coinRate = SpUtil.getDouble(Constant.coinRate, defValue: 1.0);
    String walletAmount = "0.00";
    String symbolSuffix = "";
    String letterSuffix = "";
    String noneSuffix = "";

    if (coinModel == "rmb") {
      symbolSuffix = "￥";
      letterSuffix = "CNY";
    } else {
      symbolSuffix = "\$";
      letterSuffix = "USD";
    }

    String suffix = "";
    if (type == AmountSuffixType.letter) {
      suffix = letterSuffix;
    } else if (type == AmountSuffixType.symbol) {
      suffix = symbolSuffix;
    } else {
      suffix = noneSuffix;
    }
    walletAmount = "${(NumUtil.getNumByValueStr(amount, fractionDigits: 8) / coinRate).toStringAsFixed(2)} $suffix";
    return walletAmount;
  }

  /// 获取全部存入申购/赎回记录
  Future<List<DepositRedeemModel>> getDepositAndRedeemData(String wallet) async {
    dynamic depositRecords = await DatabaseUtil.getDepositRecordData(DatabaseUtil.walletNameToTableName(wallet));
    List list = json.decode(depositRecords.toString());
    List<DepositRedeemModel> depositList = DepositRedeemModel.fromList(list);
    return depositList;
  }

  /// 获取存入申购记录
  Future<List<DepositRedeemModel>> getDepositPurchaseData(String wallet) async {
    List<DepositRedeemModel> depositList = await getDepositAndRedeemData(wallet);

    List<DepositRedeemModel> depositPurchaseList = [];
    depositList.forEach((element) {
      if (element.type == "0") {
        depositPurchaseList.add(element);
      }
    });
    return depositPurchaseList;
  }

  /// 获取存入赎回记录
  Future<List<DepositRedeemModel>> getDepositRedeemData(String wallet) async {
    List<DepositRedeemModel> depositList = await getDepositAndRedeemData(wallet);

    List<DepositRedeemModel> depositRedeemList = [];
    depositList.forEach((element) {
      if (element.type == "1") {
        depositRedeemList.add(element);
      }
    });
    return depositRedeemList;
  }

//  /// 获取已存入的ETH数量
//  Future<String> getTotalDepositNumber(String wallet) async {
//    List<DepositPurchaseModel> list = await getDepositPurchaseData(wallet);
//    double totalNum = 0.0;
//    list.forEach((element) {
//      double num = double.parse(element.fromCoins);
//      totalNum += num;
//    });
//    return NumUtil.getNumByValueDouble(totalNum, 8).toStringAsFixed(6);
//  }
//
//  /// 获取已存入的ETH金额
//  Future<String> getTotalDepositAmount(String wallet) async {
//    String totalNum = await getTotalDepositNumber(wallet);
//    CoinsBean bean = await getSingleCoinDetailModel(wallet, "ETH");
//    double totalAmount = double.parse(totalNum) * double.parse(bean.cnyBalance);
//    return NumUtil.getNumByValueDouble(totalAmount, 8).toStringAsFixed(2);
//  }
}
